package com.geese.common.util;
import java.text.DateFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;

/**
 * 时间工具类 
 */
public abstract class DateUtil {
	
	// 以T分隔日期和时间，并带时区信息，符合ISO8601规范
	public static final String PATTERN_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
	public static final String PATTERN_ISO_ON_SECOND = "yyyy-MM-dd'T'HH:mm:ssZZ";
	public static final String PATTERN_ISO_ON_DATE = "yyyy-MM-dd";

	// 以空格分隔日期和时间，不带时区信息
	public static final String PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss.SSS";
	public static final String PATTERN_DEFAULT_ON_SECOND = "yyyy-MM-dd HH:mm:ss";
	
	// 以T分隔日期和时间，并带时区信息，符合ISO8601规范
	public static final FastDateFormat ISO_FORMAT = FastDateFormat.getInstance(PATTERN_ISO);
	public static final FastDateFormat ISO_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_SECOND);
	public static final FastDateFormat ISO_ON_DATE_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_DATE);

	// 以空格分隔日期和时间，不带时区信息
	public static final FastDateFormat DEFAULT_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT);
	public static final FastDateFormat DEFAULT_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT_ON_SECOND);

	public static final long MILLIS_PER_SECOND = 1000; 
	public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; 
	public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
	public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR; 
	private static final int[] MONTH_LENGTH = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	
	/**
	 * 取得系统时间
	 */
    public static String getSysTime(String pattern) {
        return formatSysTime(FastDateFormat.getInstance(pattern));
    }

    /**
     * 格式化系统时间
     */
    private static String formatSysTime(Format format) {
    	return format.format(Calendar.getInstance().getTime());
    }
    
    /**
	 * 是否同一天.
	 */
	public static boolean isSameDay(Date date1, Date date2) {
		return DateUtils.isSameDay(date1, date2);
	}

	/**
	 * 是否同一时刻.
	 */
	public static boolean isSameTime(Date date1, Date date2) {
		// date.getMillisOf() 比date.getTime()快
		return date1.compareTo(date2) == 0;
	}
	
    /**
	 * 日期往下取整.
	 * 
	 * 如 2016-12-10 07:33:23, 如果filed为Calendar.HOUR，则返回2016-12-10 07:00:00
	 * 
	 * 如果filed为Calendar.MONTH，则返回2016-12-01 00:00:00
	 * 
	 * @param field Calendar.HOUR,Calendar.Date etc...
	 */
	public static Date truncate(Date date, int field) {
		return DateUtils.truncate(date, field);
	}

	/**
	 * 日期往上取整.
	 * 
	 * 如 2016-12-10 07:33:23, 如果filed为Calendar.HOUR，则返回2016-12-10 08:00:00
	 * 
	 * 如果filed为 Calendar.MONTH，则返回2017-01-01 00:00:00
	 * 
	 * @param field Calendar.HOUR,Calendar.Date etc...
	 */
	public static Date ceiling(Date date, int field) {
		return DateUtils.ceiling(date, field);
	}

    /**
     * date转String,默认格式yyyy-MM-dd HH:mm:ss
     * 若date为空返回空串
     * @param date
     * @return
     */
	public static String format(Date date){
		if (date == null) {
			return "";
		}
		return DateFormatUtils.format(date, PATTERN_DEFAULT_ON_SECOND);
	}

    public static String format(Date date, String pattern) {
    	return DateFormatUtils.format(date, pattern);
    }
    
    public static String format(Long millis, String pattern) {
    	return DateFormatUtils.format(millis, pattern);
	}

    public static Date addYears(Date date, int years) {
    	return DateUtils.addDays(date, years);
    }
    
    public static Date addMonths(Date date, int months) {
    	return DateUtils.addMonths(date, months);
    }
    
    public static Date addDays(Date date, int days) {
    	return DateUtils.addDays(date, days);
    }
    
    public static Date addHours(Date date, int hours) {
    	return DateUtils.addHours(date, hours);
    }
    
    public static Date addMinutes(Date date, int minutes) {
    	return DateUtils.addMinutes(date, minutes);
    }
    
    public static Date addSeconds(Date date, int seconds) {
    	return DateUtils.addSeconds(date, seconds);
    }
    
    public static Date parseDate(String str, String pattern) {
    	try {
			return DateUtils.parseDate(str, Locale.ENGLISH, pattern);
		} catch (ParseException e) {
			return null;
		}
	}
    
    public static String getSysTime() {

        return getSysTime(PATTERN_DEFAULT_ON_SECOND);
    }

    public static String getSysTimeS() {

        return getSysTime(PATTERN_DEFAULT);
    }

    public static String getSysdate() {

        return getSysTime(PATTERN_ISO_ON_DATE);
    }

    public static String getDateFormat(String str,String fromFormat, String conventFormat) throws ParseException {
        return format(parseDate(str, fromFormat), conventFormat);
    }
	
	public static String getDateFormat(String str, String conventFormat) throws ParseException {
        return format(parseDate(str, PATTERN_DEFAULT_ON_SECOND), conventFormat);
    }
	
	/**
	 * 获得日期是一周的第几天, 返回值为1是Sunday , 2是Monday....
	 * 
	 * 可通过Canendar的setFirstDayOfWeek()来改变Monday开始为1
	 */
	public static int getDayOfWeek(Date date) {
		return get(date, Calendar.DAY_OF_WEEK);
	}

	/**
	 * 获得日期是一年的第几天，返回值从1开始
	 */
	public static int getDayOfYear(Date date) {
		return get(date, Calendar.DAY_OF_YEAR);
	}

	/**
	 * 获得日期是一年的第几天，返回值从1开始.
	 * 
	 * 开始的一周，只要有一天在那个月里都算.
	 */
	public static int getWeekOfMonth(Date date) {
		return get(date, Calendar.WEEK_OF_MONTH);
	}

	/**
	 * 获得日期是一年的第几周，返回值从1开始.
	 * 
	 * 开始的一周，只要有一天在那一年里都算.
	 */
	public static int getWeekOfYear(Date date) {
		return get(date, Calendar.WEEK_OF_YEAR);
	}
	
	private static int get(final Date date, int field) {
		Validate.notNull(date, "The date must not be null");
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(field);
	}
	
	/**
	 * 设置年份, 公元纪年.
	 */
	public static Date setYears(Date date, int amount) {
		return DateUtils.setYears(date, amount);
	}

	/**
	 * 设置月份, 0-11.
	 */
	public static Date setMonths(Date date, int amount) {
		return DateUtils.setMonths(date, amount);
	}

	/**
	 * 设置日期, 1-31.
	 */
	public static Date setDays(Date date, int amount) {
		return DateUtils.setDays(date, amount);
	}

	/**
	 * 设置小时, 0-23.
	 */
	public static Date setHours(Date date, int amount) {
		return DateUtils.setHours(date, amount);
	}

	/**
	 * 设置分钟, 0-59.
	 */
	public static Date setMinutes(Date date, int amount) {
		return DateUtils.setMinutes(date, amount);
	}

	/**
	 * 设置秒.
	 */
	public static Date setSeconds(Date date, int amount) {
		return DateUtils.setSeconds(date, amount);
	}

	/**
	 * 设置毫秒.
	 */
	public static Date setMilliseconds(Date date, int amount) {
		return DateUtils.setMilliseconds(date, amount);
	}

	/**
	 * 两个日期相差多少个月
	 */
	public static int countMonths(String end, String start, String pattern) throws ParseException {

		Calendar calend = Calendar.getInstance();
		calend.setTime(parseDate(end, pattern));

		Calendar calstart = Calendar.getInstance();
		calstart.setTime(parseDate(start, pattern));

		return (calend.get(Calendar.YEAR) * 12 + calend.get(Calendar.MONTH)) 
				- (calstart.get(Calendar.YEAR) * 12 + calstart.get(Calendar.MONTH));
	}
	

	/**
	 * 格式化时间
	 */
    public static String formatTime(String str, String strpattern, String pattern, String TimeZoneFormat) {
		FastDateFormat dateFormat = FastDateFormat.getInstance(strpattern);
		Date date = null;
		try {
			date = (Date) dateFormat.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
			return "";
		}
		FastDateFormat format = FastDateFormat.getInstance(pattern, TimeZone.getTimeZone(TimeZoneFormat));
		String time = format.format(date);
		return time;
	}

	/**
	 * 是否闰年.
	 */
	public static boolean isLeapYear(Date date) {
		return isLeapYear(get(date, Calendar.YEAR));
	}

	/**
	 * 是否闰年，移植Jodd Core的TimeUtil
	 * 
	 * 参数是公元计数, 如2016
	 */
	public static boolean isLeapYear(int y) {
		boolean result = false;

		if (((y % 4) == 0) && // must be divisible by 4...
				((y < 1582) || // and either before reform year...
						((y % 100) != 0) || // or not a century...
						((y % 400) == 0))) { // or a multiple of 400...
			result = true; // for leap year.
		}
		return result;
	}

	/**
	 * 获取某个月有多少天, 考虑闰年等因数, 移植Jodd Core的TimeUtil
	 */
	public static int getMonthLength(Date date) {
		int year = get(date, Calendar.YEAR);
		int month = get(date, Calendar.MONTH);
		return getMonthLength(year, month);
	}

	/**
	 * 获取某个月有多少天, 考虑闰年等因数, 移植Jodd Core的TimeUtil
	 */
	public static int getMonthLength(int year, int month) {

		if ((month < 1) || (month > 12)) {
			throw new IllegalArgumentException("Invalid month: " + month);
		}
		if (month == 2) {
			return isLeapYear(year) ? 29 : 28;
		}

		return MONTH_LENGTH[month];
	}

	/**
	 * 秒转换成分钟
	 */
	public static String secondtoMinutesecond(long second){
		String result = "";
		result = second/60 > 0 ? second/60 + "分" : "";
		result = result + (second%60 > 0 ? (second%60 + "秒") : (!result.equals("")) ? "钟" : "0分钟");
		return result;
	}
	
	/**
	 * 打印用户友好的，与当前时间相比的时间差，如刚刚，5分钟前，今天XXX，昨天XXX
	 */
	public static String formatFriendlyTimeSpanByNow(long timeStampMillis) {
		long now = System.currentTimeMillis();
		long span = now - timeStampMillis;
		if (span < 0) {
			// 'c' 日期和时间，被格式化为 "%ta %tb %td %tT %tZ %tY"，例如 "Sun Jul 20 16:17:00 EDT 1969"。
			return String.format("%tc", timeStampMillis);
		}
		if (span < MILLIS_PER_SECOND) {
			return "刚刚";
		} else if (span < MILLIS_PER_MINUTE) {
			return String.format("%d秒前", span / MILLIS_PER_SECOND);
		} else if (span < DateUtil.MILLIS_PER_HOUR) {
			return String.format("%d分钟前", span / MILLIS_PER_MINUTE);
		}
		// 获取当天00:00
		long wee = truncate(new Date(now), Calendar.DATE).getTime();
		if (timeStampMillis >= wee) {
			// 'R' 24 小时制的时间，被格式化为 "%tH:%tM"
			return String.format("今天%tR", timeStampMillis);
		} else if (timeStampMillis >= wee - MILLIS_PER_DAY) {
			return String.format("昨天%tR", timeStampMillis);
		} else {
			// 'F' ISO 8601 格式的完整日期，被格式化为 "%tY-%tm-%td"。
			return String.format("%tF", timeStampMillis);
		}
	}
	
	public static String getWeekOfDate(String time) { 
    	Date date = format(time, "yyyy-MM-dd HH:mm:ss");
        String[] weekDaysName = { "周日", "周一", "周二", "周三", "周四", "周五", "周六" };
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int intWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        return weekDaysName[intWeek];
	}
	
	public static Date format(String str, String pattern) {
	
		DateFormat formatter = new SimpleDateFormat(pattern, Locale.ENGLISH);
	
		Date date = null;
		try {
			date = (Date) formatter.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	
		return date;
	}
	
	/**
	 * 两个日期相差多少小时(整数)
	 */
	public static long countHour(String end, String start, String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		long endLong = 0;
		long startLong = 0;
		try {
			endLong = format.parse(end).getTime();
			startLong = format.parse(start).getTime();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		long time = (endLong-startLong)/3600000;
		return time;
	}
	
	/**
	 * 获取当前时间戳
	 */
	public static long getCurrentTimeStamp() {
		return System.currentTimeMillis() / 1000;
	}
	
}
